﻿#include "MainWindow.h"
#include "ui_MainWindow.h"
#include "SysTrayIcon.h"
#include "MenuButton.h"

#include "global/const.h"
#include "stores/DataStroes.h"
#include "services/tlv/Hardware/SerialTlv.h"
#include "services/tlv/Com/TlvThreadCom.h"
#include "services/Task/TlvCmdTask.h"
#include "services/Task/TlvCodeTask.h"
#include "components/Toast/Toast.h"
#include "components/GuideManager/GuideManager.h"
#include "views/Hardware/SerialDialog/SerialDialog.h"
#include "views/Project/OpenPrjDialog/OpenPrjDialog.h"
#include "views/Project/NewPrjDialog/NewPrjDialog.h"
#include "views/Help/SettingDialog/SettingDialog.h"
#include "views/Help/HelpDialog/HelpDialog.h"
#include "views/Help/AboutDialog/AboutDialog.h"
#include "views/Tool/TestBoxUpdaterDialog/TestBoxUpdaterDialog.h"
#include "views/Tool/TouchToolWidget/TouchToolWidget.h"
#include "views/Tool/TIScriptWidget/TIScriptWidget.h"

#include <QAction>
#include <QMenu>
#include <QShortcut>
#include <QDebug>


MainWindow::MainWindow(QWidget *parent)
    : BaseWindow(parent)
    , ui(new Ui::MainWindow)
    , m_tray(new SysTrayIcon(APP_NAME, this))
    , m_btnMenu(new MenuButton(this))
{
    Toast::setToastParent(this);  // 先设置Toast的父窗口再渲染界面

    ui->setupUi(this);

#if !FULL_VERSION
    // 轻量版本，移除代码编辑页面，隐藏tabbar
    ui->twWorkspace->removeTab(1);
    ui->twWorkspace->setTabBarAutoHide(true);
#endif

    resize(1280, 760);
    showMaximized();

    setWindowTitle();

    initSignalSlot();
    initShortcut();
    initView();

    // 启动时自动检查版本
    QProcess::startDetached(StoreFilePath::updateAppFilePath(), {"--auto"});

    // 解决弹出位置不在窗口底部的问题
    QTimer::singleShot(100, this, &MainWindow::showSomeStatus);
}

MainWindow::~MainWindow()
{
    SerialTlv::instance()->deleteLater();
    TlvThreadCom::instance()->deleteLater();
    DataStroes::instance()->deleteLater();
    delete ui;
}

void MainWindow::setWindowTitle()
{
    QString title = QString("Tlv Tool (%1)").arg(tr("No project opened"));
    auto& model = DataStroes::instance()->tlvPrj()->model();
    if (model.isValid()) {
        title = QString("Tlv Tool (%1)  [ %2 ]").arg(model.data().name).arg( DataStroes::instance()->tlvPrj()->latestProject());
    }
    BaseWindow::setWindowTitle(title);
}

void MainWindow::initSignalSlot()
{
    connect(m_btnMenu, &MenuButton::showGuideTriggered, this, &MainWindow::onShowGuideTriggered);
    connect(m_btnMenu, &MenuButton::backgroundImageChanged, this, &MainWindow::initBackground);
}

void MainWindow::initView()
{
    ui->twWorkspace->setBarStyle2();

    // 触摸工具窗口
    m_touchWgt = new TouchToolWidget(this);
    addDockWidget(Qt::RightDockWidgetArea, m_touchWgt);
    // m_touchWgt->setFloating(true);
    m_touchWgt->hide();

    // TI脚本窗口
    m_tiWgt = new TIScriptWidget(this);
    addDockWidget(Qt::RightDockWidgetArea, m_tiWgt);
    // m_tiWgt->setFloating(true);
    m_tiWgt->hide();

    // 菜单按钮
    titleBar()->addStandardButton(m_btnMenu);

    // 设置背景图片
    initBackground();
}

void MainWindow::initBackground()
{
    QString imgPath = DataStroes::instance()->settings()->model().data().general.background_imgae;
    if (imgPath.isEmpty()) {  // 空值显示默认图片
        imgPath = StoreFilePath::defaultBackgroundImagePath();
        setGlobalBackgroundImage(imgPath);
    } else if (imgPath != "$") {  // $ 值不显示图片
        setGlobalBackgroundImage(imgPath);
    }
}

void MainWindow::initShortcut()
{
    QShortcut *ctrl_o = new QShortcut(QKeySequence("Ctrl+O"), this);
    connect(ctrl_o, &QShortcut::activated, this, &MainWindow::on_btnPrjOpen_clicked);

    QShortcut *ctrl_n = new QShortcut(QKeySequence("Ctrl+N"), this);
    connect(ctrl_n, &QShortcut::activated, this, &MainWindow::on_btnPrjNew_clicked);

    QShortcut *ctrl_s = new QShortcut(QKeySequence("Ctrl+S"), this);
    connect(ctrl_s, &QShortcut::activated, this, &MainWindow::on_btnPrjSave_clicked);

    QShortcut *ctrl_alt_1 = new QShortcut(QKeySequence("Ctrl+Alt+1"), this);
    connect(ctrl_alt_1, &QShortcut::activated, this, &MainWindow::on_btnHWSerial_clicked);
}

void MainWindow::showSomeStatus()
{
    // 项目打开状态：
    auto& modelPrj = DataStroes::instance()->tlvPrj()->model();
    QString prjPath = DataStroes::instance()->tlvPrj()->latestProject();
    if (modelPrj.isValid()) {
        Toast::success(tr("Open project successfully!\n") + prjPath, 3000);
    } else if (!prjPath.isEmpty()) {  // 未打开项目就不弹出弹窗了，打开失败再弹出
        Toast::error(tr("Open project failed!\n") + prjPath, 3000);
    }

    // 用户引导状态：
    auto& modelSetting = DataStroes::instance()->settings()->model();
    if (modelSetting.data().general.show_guide) {
        onShowGuideTriggered();
        modelSetting.data().general.show_guide = false;
        DataStroes::instance()->settings()->save();
    } else {
        ui->btnHWSerial->click();
    }
}

void MainWindow::closeEvent(QCloseEvent* e)
{
    e->ignore();
    hide();
    m_tray->show();
}

void MainWindow::onShowGuideTriggered()
{

    GuideManager *guide = new GuideManager(this);

    guide->addStep(
                ui->tabWidget,
                tr("Here are the project operations: open, create, save"),
                [this](){ ui->tabWidget->setCurrentIndex(0); }
    );
    guide->addStep(
                ui->tabWidget,
                tr("Hardware communication devices, \nsuch as serial ports, can be connected here"),
                [this](){ ui->tabWidget->setCurrentIndex(1); }
    );
    guide->addStep(
                ui->tabWidget,
                tr("Here are some tools"),
                [this](){ ui->tabWidget->setCurrentIndex(2); }
    );
    guide->addStep(
                ui->tabWidget,
                tr("Here are the app settings and information"),
                [this](){ ui->tabWidget->setCurrentIndex(3); }
    );
    guide->addStep(
                ui->twWorkspace,
                tr("Here is the command workspace, you can edit the command"),
                [this](){ ui->tabWidget->setCurrentIndex(0); ui->twWorkspace->setCurrentIndex(0); }
    );
    guide->addStep(
                ui->twWorkspace,
                tr("This is the code workspace where you can edit JavaScript code. \nSpecific API usage can be found in Help-Help"),
                [this](){ ui->twWorkspace->setCurrentIndex(1); }
    );
    guide->addStep(
                ui->dockWidget,
                tr("This is the log area, where command sending results \nand code execution results will be displayed"),
                [this](){ ui->twWorkspace->setCurrentIndex(0); }
    );

    guide->start();

    // 结束后销毁
    connect(guide, &GuideManager::finished, guide, &GuideManager::deleteLater);
}

void MainWindow::on_btnHWSerial_clicked()
{
    SerialDialog(this).exec();
}

void MainWindow::on_btnPrjOpen_clicked()
{
    OpenPrjDialog(this).exec();
}


void MainWindow::on_btnPrjNew_clicked()
{
    NewPrjDialog(this, NewPrjDialog::Create).exec();
}

void MainWindow::on_btnPrjSave_clicked()
{
    ui->tabCmd->toCmdsModel();
    ui->tabCode->toCodesModel();
    TlvProject* prj = DataStroes::instance()->tlvPrj();
    if (prj->model().isValid()) {
        if (prj->save()) {
            Toast::success(tr("Save Successfully!"));
        } else {
            Toast::error(tr("Save Failed!"));
        }
    } else {
        NewPrjDialog(this, NewPrjDialog::SaveAs).exec();
    }
}

void MainWindow::on_btnPrjSaveAs_clicked()
{
    ui->tabCmd->toCmdsModel();
    ui->tabCode->toCodesModel();
    NewPrjDialog(this, NewPrjDialog::SaveAs).exec();
}


void MainWindow::on_btnPrjQuit_clicked()
{
    qApp->quit();
}


void MainWindow::on_btnToolTBU_clicked()
{
    // 升级的前提：cmdTask和codeTask不在运行中！
    TlvCmdTask* task1 = TlvCmdTask::instance();
    if (task1->isRunning()) {
        Toast::warning( ITask::WARN_TASK_IS_RUNNING(task1->taskName()) );
        return;
    }
    TlvCodeTask* task2 = TlvCodeTask::instance();
    if (task2->isRunning()) {
        Toast::warning( ITask::WARN_TASK_IS_RUNNING(task2->taskName()) );
        return;
    }
    TestBoxUpdaterDialog(this).exec();
}


void MainWindow::on_btnHelpSetting_clicked()
{
    SettingDialog(this).exec();
}


void MainWindow::on_btnHelpAbout_clicked()
{
    AboutDialog(this).exec();
}


void MainWindow::on_btnHelpHelp_clicked()
{
    HelpDialog(this).exec();
}


void MainWindow::on_btnTouchTool_clicked()
{
    m_touchWgt->show();
}


void MainWindow::on_btnTiScript_clicked()
{
    m_tiWgt->show();
}

